package com.mdp.im.core.socket;

import com.mdp.core.SpringUtils;
import com.mdp.im.core.scbscriber.api.ImChannelConfig;
import com.mdp.im.core.vo.SimpleUser;
import com.mdp.im.core.utils.TopicTools;
import com.mdp.im.core.service.ImLoginUtils;
import com.mdp.mq.sp.ChannelConfig;
import io.netty.channel.Channel;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.ImmediateEventExecutor;
import org.springframework.data.redis.listener.ChannelTopic;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 通道持有者类
 * 
 * @author chenyc
 * @date 2020/3/29
 */
public class ChannelsHolder {
    
    public static int capacity=20000;
    /**
     * {groupId,ChannelGroup}
     * 群组对话下的ChannelGroup
     * group会自动监测里面的channel，当channel断开时，会主动踢出该channel，永远保留当前可用的channel列表 。
     */
    private static final Map<String, ChannelGroup> CHANNEL_GROUPS = new ConcurrentHashMap<>(capacity);
     
    private static final DefaultChannelGroup DEFAULT_CHANNEL_GROUP = new DefaultChannelGroup(ImmediateEventExecutor.INSTANCE);
    
    /**
     * {channelId,Channel}
     * channel列表 
     */
    private static final Map<String, Channel> CHANNELS = new ConcurrentHashMap<>(capacity);
   
    /**
     * {userid,[channelId1,channelId2]}
     * 用户和Channel对应关系哈希Map
     */
    private static final Map<String, Set<String>> USER_CHANNEL_IDS = new ConcurrentHashMap<>(capacity);
    
    /**
     * {channelId,{userid,username,sex,headimgurl}}
     * Channel和用户对应关系哈希Map
     */
    private static final Map<String, SimpleUser> CHANNEL_USER = new ConcurrentHashMap<>(capacity);
    

    
    public static Map<String, ChannelGroup> getChannelGroups() {
        return CHANNEL_GROUPS;
    }
    
    /**
     * 添加Channel
     * @param user
     * @param channel
     */
    public static void addChannel(SimpleUser user, Channel channel) {
    	addChannel(channel);
        String channelId = channel.id().asLongText(); 
        Set<String> channelIds = new HashSet<String>();
        channelIds.add(channelId);
        Set<String> returnSet = USER_CHANNEL_IDS.putIfAbsent(user.getUserid(), channelIds);
        if(returnSet != null) {
            returnSet.add(channelId);
        } 
        CHANNEL_USER.putIfAbsent(channelId, user);
    }
    /**
     * 添加Channel 
     * @param channel
     */
    public static void addChannel(Channel channel) {
    	CHANNELS.putIfAbsent(channel.id().asLongText(), channel);
    	addChannelToDefaultGroup(channel);
    }
    
    
    public static void addChannelToDefaultGroup(Channel channel) {
    	Channel channel2=DEFAULT_CHANNEL_GROUP.find(channel.id());
    	if(channel2==null) {
    		DEFAULT_CHANNEL_GROUP.add(channel);
    	}
    	
    }
    public static ChannelGroup getDefaultGroup() {
    	return DEFAULT_CHANNEL_GROUP;
    }
    /**
     * 删除Channel
     * @param channelId
     */
    public static void removeChannel(String channelId) {
        SimpleUser user = CHANNEL_USER.get(channelId);
        if(user != null) {
            Set<String> channelIds = USER_CHANNEL_IDS.get(user.getUserid());
            if(channelIds != null) {
                if(channelIds.remove(channelId)) {
                    if(channelIds.size() == 0) {
                        USER_CHANNEL_IDS.remove(user.getUserid());
                    }
                }
            }
            ImLoginUtils.removeChannelId(user.getUserid(),channelId);
        }
        Channel channel=CHANNELS.get(channelId);
        if(channel!=null && channel.isActive() ){
            channel.close();
        }
        CHANNELS.remove(channelId);
        CHANNEL_USER.remove(channelId);  
    }
    
    /**
     * 根据频道id得到用户简单信息{userid,username,sex,headimgurl}
     * @param channelId
     * @return
     */
    public static SimpleUser getSimpleUserByChannelId(String channelId) {
        return CHANNEL_USER.get(channelId);
    } 
    
    /**
     * 根据用户id得到channel集合
     * @param userid
     * @return
     */
    public static Set<String> getChannelIdsByUserid(String userid) {
        return USER_CHANNEL_IDS.get(userid);
    }
    
    /**
     * 根据channel id得到channel
     * @param channelId
     * @return
     */
    public static Channel getChannelById(String channelId) {
        return CHANNELS.get(channelId);
    }
    /**
     * 将channel添加到GroupChannel中
     * @param groupId
     * @param channel
     */
    public static void addChannelToGroup(String groupId, Channel channel) {
        DefaultChannelGroup channelGroup = new DefaultChannelGroup(ImmediateEventExecutor.INSTANCE);
        ChannelGroup returnChannelGroup = CHANNEL_GROUPS.putIfAbsent(groupId, channelGroup);
        if(returnChannelGroup==null) {
            // 不存在该ChannelGroup，第一次添加。需要启动redis消息监听器
            ImChannelConfig config= SpringUtils.getBean(ImChannelConfig.class);
            config.addMessageListener(new ChannelTopic(TopicTools.getGroupTopicName(groupId)));
            channelGroup.add(channel);
            return;
        }
        if(returnChannelGroup.size()==0){
            ImChannelConfig config=SpringUtils.getBean(ImChannelConfig.class);
            config.addMessageListener(new ChannelTopic(TopicTools.getGroupTopicName(groupId)));
            returnChannelGroup.add(channel);
            return;
        }
        // ChannelGroup已经存在
        if(returnChannelGroup.contains(channel)) {
        	return;
        }
        returnChannelGroup.add(channel);
    }
    /**
     * 将channel移除GroupChannel中
     * @param groupId
     * @param channel
     */
    public static void removeChannelFromGroup(String groupId, Channel channel) { 
        ChannelGroup returnChannelGroup = CHANNEL_GROUPS.get(groupId);
        if(returnChannelGroup == null) {
            ImChannelConfig config=SpringUtils.getBean(ImChannelConfig.class);
            config.removeMessageListener(new ChannelTopic(TopicTools.getGroupTopicName(groupId)));
            return;
        }
        returnChannelGroup.remove(channel);
        //如果所有人都退出了，应该取消消息监听
        if(returnChannelGroup.size()==0){
            CHANNEL_GROUPS.remove(groupId);
            ImChannelConfig config=SpringUtils.getBean(ImChannelConfig.class);
            config.removeMessageListener(new ChannelTopic(TopicTools.getGroupTopicName(groupId)));
        }
    }
    /**
     * 添加IM Channel Id
     * @param channelId
     * @param IMChannelId
     */
//    public static void addIMChannel(String channelId, String IMChannelId) {
//        CHANNEL_IM_CHANNELS.put(channelId, IMChannelId);
//    }
    
    /**
     * 移除IM Channel Id
     * @param channelId
     */
//    public static void removeIMChannel(String channelId) {
//        CHANNEL_IM_CHANNELS.remove(channelId);
//    }
    
    /**
     * 得到所用用户id
     * @return
     */
    public static Set<String> getUserids() {
        return USER_CHANNEL_IDS.keySet();
    } 
    
    public static void removeGroup(String groupId) {
    	CHANNEL_GROUPS.remove(groupId);
    }

}
